/*
 * This parameter list is for clipper which has been changed  from PerM's Parameterlist class
 */
#include "ParameterList.h"
using namespace std;

MappingOpts::MappingOpts(void)
{
    this->setDefaults();
}

MappingOpts::~MappingOpts(void)
{
    ;
}

void MappingOpts::setDefaults(void)
{
    this->fullCommand = string("clip");
    this->readLength = MIN_READ_LENGTH;
    this->anchorLength = MIN_READ_LENGTH / 4;
    this->subDiffThreshold = 1;
    this->bIgnoreQS = false;
    // Output all the best alignments in terms of # of mismatches by default.
    this->bPrintSamHeader = true;
    this->bDiscardReadWithN = true;
    this->bExcludeAmbiguousReads = false;
    this->bGetAllDelAlignments = false;
    this->bCanoicalOnly = false;
    this->bGetAllAlignments = true; // For anchor only
    this->bPrintUnMappedReads = false;
    this->bPrintRef = false; // In the output sam file, print corresponding ref Seqs instead of reads.
    // I/O.
    readtag_delimiter = ',';
    strcpy(this->readsFileFormat, "");
    strcpy(this->outputDir, "");
    strcpy(this->outputFileN, "");
    strcpy(this->outputFormat, "sam");
    strcpy(this->unmappedFileN, "");
    // deletion length
    const unsigned int DEFAULT_UPPER_BOUND = 1000000;
    this->disUB = DEFAULT_UPPER_BOUND;
    this->disLB = 0;
    this->anchorLength = 0;
    this->MEMES = 0; // minimal Match on Either Side
    this->bUniqueMapOnly = false;

    this->filteredRepeatBases = 0;
    this->filteredDummyBases = 0;
    this->bFileterRepeatRead = false;
    this->bFileterDummyRead = false;
    this->bTest = false;
}

void MappingOpts::clearOutputFileName(bool clear)
{
    if (clear) {
        strcpy(this->outputFileN, "");
        strcpy(this->unmappedFileN, "");
    }
}

ParameterList::ParameterList()
{
    setDefaults();
}

void ParameterList::setDefaults()
{
    this->validFlag = true;
    this->refFormat == "unknown";
    strcpy(refFile, "ref");
    strcpy(readsFile, "reads");
    strcpy(this->indexFileN, "");
    strcpy(this->seedName, "");
    this->seedId = 1;
    // Index
    this->bMakeIndex = false;
    this->bSaveIndex = false;
    // Reads files
    this->bMappedLongRead = false;
    this->bMappedSOLiDRead = false;
    this->bMaskedMathRepeat = false;
    strcpy(this->qualityFile, "");
    this->truncatedReadLength = MAX_LINE;
}

// This function decide options base on the ext name of some options
int selectSeed(ParameterList& P)
{
    string seed(P.seedName);
    if ( seed == "F0") {
        return(0);
    } else if ( seed == "F1") {
        return(1);
    } else if ( seed == "F2") {
        return(2);
    } else if (seed == "S11") {
        return(11);
    } else if (seed == "F3") {
        return(3);
    } else if (seed == "F4") {
        return(4);
    } else if (seed == "S20") {
        return(20);
    } else if (seed == "S12") {
        return(12);
    } else {
        if (P.subDiffThreshold == 0) {
            myStrCpy(P.seedName, "F0", FILENAME_MAX);
            return(0);
        }
        unsigned int queryLength = (P.anchorLength > 0 ? P.anchorLength: P.readLength);
        if (P.bMappedSOLiDRead) {
            if (queryLength <= 25) {
                return(2);
            } else if (queryLength <= 35) {
                return(11);
            }
        } else {
            if (queryLength <= 35) {
                return(2);
            }
        }
    }
    // current don't provide higher full sensitivity seed
    return(3);
}

// This function decide options base on the ext name of some options
void ParameterList::getOptsByCheckingExtName(void)
{
    // fixed the --readsFormat input
    char c = this->readsFileFormat[0];
    if (c != '\0' && c != '.') {
        strcpy(&this->readsFileFormat[1], string(this->readsFileFormat).c_str());
        this->readsFileFormat[0] = '.';
    }

    // choose the output format by ext name
    const char* extName;
    extName = getExtName(this->outputFileN);
    if (extName[0] == '.') {
        if (extName[1] == 'm' || extName[1] == 's') {
            myStrCpy(this->outputFormat, &extName[1], FILENAME_MAX);
        }
    }
    // incomplete
}

bool ParameterList::checkRefValidity(void)
{
    if (!fileExist(this->refFile)) {
        LOG_INFO("Info %d: Reference file %s is not found.\n",\
                 ERROR_LOG, this->refFile);
        this->validFlag = false;
    } else if (!(withFastaExtFileName(this->refFile) || \
                 hasTheExtName(this->refFile, ".dat") || \
                 hasTheExtName(this->refFile, ".txt") || \
                 hasTheExtName(this->refFile, ".index")) &&\
               !(this->refFormat == "fasta" ||\
                 this->refFormat == "list" ||\
                 this->refFormat == "index" )) {
        LOG_INFO("\nInfo %d: Reference %s has an unexpected ext name.\n",\
                 ERROR_LOG, this->readsFile);
        this->validFlag = false;
        printSynopsis();
    }
    return(this->validFlag);
}

bool ParameterList::truncatReadLength(void)
{
    // Truncated reads if opts are specified
    if (this->readLength > this->truncatedReadLength) {
        this->readLength = this->truncatedReadLength;
        LOG_INFO("Info %d: Read length is truncated to %d bp\n", INFO_LOG, this->readLength);
    }

    if (this->bMappedSOLiDRead && this->readLength > MAX_READ_LENGTH) {
        this->readLength = MAX_READ_LENGTH; // Truncated to read length 64 for SOLiD read.
    } else if (this->readLength > MAX_READ_LENGTH * 2) {
        cout << "Read length " << this->readLength << \
             " is longer than the maximum read length. " << MAX_READ_LENGTH <<".\n";
        return(false);
    } else if (this->readLength < MIN_READ_LENGTH) {
        cout << "Read length " << this->readLength << \
             " is shorter than the minimum read length. " << MIN_READ_LENGTH <<".\n";
        return(false);
    }
    return(true);
}

unsigned int getAnchorLength(unsigned int readLength, unsigned int setAnchorLength)
{
    // TODO handle exception if read are too long.
    int MIN_ANCHOR_LENGTH = 17;
    if (readLength >= (int)MIN_READ_LENGTH) {
        if (setAnchorLength > 0) {
            if (setAnchorLength <= (unsigned int)MIN_ANCHOR_LENGTH) {
                return(MIN_ANCHOR_LENGTH);
            } else {
                return(setAnchorLength);
            }
        } else {
            return(min(readLength/4, MAX_ANCHOR_LENTH));
        }
    }
    return(MIN_ANCHOR_LENGTH); // too small for anchor length
}

unsigned int nonSpaceCharCount(const char* str)
{
    unsigned int returnValue = 0;
    for (int i = 0; str[i] != '\0'; i++) {
        if (!(isspace(str[i]))) {
            returnValue++;
        }
    }
    return(returnValue);
}

// Return the read length given a line in the reads input file
unsigned int getReadLength(char* line, char cFileType)
{
    unsigned int readLength = 0;
    switch (cFileType) {
    case 'F': // Given the reads file are fasta format
    case 'q':
        readLength = (unsigned int) nonSpaceCharCount(line);
        return (readLength);
    case 'S': // Given the reads file are SOLiD format
    case 'Q':
        readLength = (unsigned int) nonSpaceCharCount(line) - 1;
        return (readLength);
    default:
        return MIN_READ_LENGTH;
    }
}

bool isSkipLines(const char* line)
{
    return(!isNucleotide(line[0]));
}

// Must add new reads estimate function to support other reads format.
unsigned int getReadLength(const char* readFile, char expFileFormat)
{
    char cFileType;
    if (expFileFormat != 'N') {
        cFileType = expFileFormat;
    } else {
        cFileType = getReadsFileFormatSymbol(readFile);
    }

    ifstream ifile(readFile);
    char seqLine[MAX_LINE];
    do {
        seqLine[0] = EOF;
        ifile.getline(seqLine, MAX_LINE, '\n');
        if (seqLine[0] == EOF) {
            cout << "The read length can not be decided from the input format." << endl;
            return(MIN_READ_LENGTH);
        }
    } while (isSkipLines(seqLine));

    unsigned int readLength = getReadLength(seqLine, cFileType);
    // Add the extra read length if it is printed in the following second line.
    if (readLength >= MAX_READ_LENGTH) {
        ifile.getline(seqLine, MAX_LINE, '\n');
        if (!(isSkipLines(seqLine))) {
            readLength += getReadLength(seqLine, cFileType);
        }
    }
    return (readLength);
}


void printExample(void)
{
    cout << "Ex:  ./clip Ref.fa Reads.fa --anchorL 25 --seed F1 -e -v 5 -m -s" << endl;
    cout << "Clipper uses the first and last 25 bp as anchor; each end allows one mismatch." << endl;
    cout << "Clipper reports only the uniquely mapped reads within 5 mismatches." << endl;
    cout << "Clipper reconstructs and save the indexes to the default path for future mappings." << endl;
    cout << endl;
}

void printIoInfo(void)
{
    cout << "<Reference Input>" << endl;
    cout << "The reference file should be in the fasta format, with *.fa or *.fasta ext filename." << endl;
    cout << "It can be transcriptom, with multiple seqs separated by lines start with '>' and the ref seq name." << endl;
    cout << "If you have multiple files, you can put each file path a line in a .txt file." << endl;
    cout << "ex: chr1.fa\\n chr2.fa\\n .. etc, with each path in one row." << endl;
    cout << "Clipper also takes the txt file as ref, a file listing paths allreference paths." << endl;
    cout << "Clipper parses a ref file according to it's ext name, which can be overwritten by --refFormat flag."<< endl;
    cout << endl;
    cout << "<Reads Input>" << endl;
    cout << "The reads file should be in the .fasta, or .fastq format." << endl;
    cout << "Clipper parses a reads file according to it's ext name, which can be overwritten by --readFormat flag."<< endl;
    cout << "Large reads file can be split to small files. Make *.txt file with each line a path of the reads." << endl;
    cout << "Use the txt file as the reads input so Clip can map reads set in parallels." << endl;
    cout << "Clipper's output mapping result in sam format. " << endl;
    cout << endl;
}

void printDefault(void)
{
    cout << "When you type:" << endl;
    cout << "\tclip <ref> <reads> for single end read mapping" << endl;
    cout << endl;
    cout << "Clipper uses its default options, which can be overwritten by the options flags." << endl;
    cout << "The min and max of deletion are 0 and 1Mb in a same ref, respectively" << endl;
    cout << "By default, Clip outputs all the best alignments in terms of the mismatches number." << endl;
    cout << "It throw away all reads with 'N' or '.' unless --includeReadsWN is specified" << endl;
    cout << "The default seeds varied in different the read lengths and types." << endl;
    cout << "It won't save the index if -s is not specified." << endl;
    cout << "When -s is specified but not follow a path, a default filename is used to save the index." << endl;
    cout << "That path will be test for index reused for the mapping next time." << endl;
    cout << "The input formats are decided by the the ext name. The output file is in .sam format." << endl;
    cout << "unless special flags are set to overwrite the guess." << endl;
    cout << endl;
}

void printOptionsInfo(void)
{
    cout << "Options for del mapping:" << endl;
    /*
    cout << "-B     Output all best alignments in terms of mismatches, within the threshold." << endl;
    cout << "-E     Output only the uniquely mapped reads." << endl;
    */
    cout << "-a     Output all deletion alignments within the mismatch threshold." << endl;
    cout << "-e     Exclude ambiguous deletion. " << endl;
    cout << "-v I   where I is an integer, the num of mismatches allowed" << endl;
    cout << "-T I   where I is an integer, the truncated read length" << endl;
    cout << "-L I   Specify deletion lower bound" << endl;
    cout << "-U I   Specify deletion upper bound" << endl;
    cout << "-m     Make the reference index without reusing the saved index." << endl;
    cout << "-s P   Save the reference index to the path P" << endl;
    cout << "-o P   where P is the path for single read set" << endl;
    cout << "-u P   Output the unmapped reads in to a fasta file." << endl;
    cout << endl;
    cout << "--anchorL I   where I is an integer, the length of anchor region in the two end." << endl;
    cout << "--ignoreRepeatR I    Reads that has repeat necleotides over I (a integer) times will be filtered." << endl;
    cout << "--ignoreDummyR I   Reads that has a kind of nucleotides with frequency more than I will be filtered." << endl;
    cout << "--delimiter 'c', where c is the delimiter of the read id, for strange format of read files." << endl;
    cout << "--refFormat {fasta | list | index }. Take refs file in the specified format," << endl;
    cout << "instead of gussing according to its ext name." << endl;
    cout << "--readFormat {fasta | fastq | csfasta | csfastq}. Take reads file in the specified format," << endl;
    cout << "instead of gussing according to its ext name." << endl;
    cout << "--seed {F0 | F1 |F2 | F3}.  allow full sensitivity to one or two mismatches in the anchor regions." << endl;
    cout << "--bestAnchor   Use the best mapped anchored region only to speed up speed." << endl;
    cout << "--canonicalJunc Let canonical Junctions always be prefered than non-canoical junction." << endl;
    cout << "--noSamHeader  Do not print the sam header." << endl;
    cout << "--ignoreQS Ignore the quality scores in fastq or QUAL files." << endl;
    cout << "--includeReadsWN Do not filter out read with 'N' or '.' as default." << endl;
    cout << "--statsOnly Do not print alignments, show statistic only." << endl;
    cout << endl;
    printExample();
}

void printSynopsis(void)
{
    cout << "Clip (Efficient read mapping with periodic full sensitive seeds)" << endl;
    cout << "Version: 0.0.8 \n" << endl;
    cout << "Synopsis:" << endl;
    cout << "Clip <reference or index path> <read length or reads path > <-flag options>" << endl;
    cout << "Ex:  clip Ref.fasta Reads.fa --anchorL 17 -seed F0 -e -v 5 -o out.sam" << endl;
    cout << "Ex:  clip RefFilesList.txt ReadsFileList.txt -e -v 3 -U 1000 -L 0 -m -s my.index" << endl;
    cout << "Ex:  clip Ref.index ReadsSetFilesList.txt -a -b > my.log" << endl;
    cout << endl;
    cout << "Please type" << endl;
    cout << "clip io            (to see the I/O format)" << endl;
    cout << "clip default       (to see the default opt setting)" << endl;
    cout << "clip options       (to see the full list of opt)" << endl;
    cout << "For more info, please check: http://code.google.com/p/clippers/" << endl;
    cout << endl;
}

void printUsageInfo(string helepOpt)
{
    if (helepOpt == "io") {
        printIoInfo();
    } else if (helepOpt == "default") {
        printDefault();
    } else if (helepOpt == "options") {
        printOptionsInfo();
    } else {
        printSynopsis();
    }
}

bool checkArg(int argc, const char** argv, const char* arg)
{
    for (int i = 1; i < argc; i++) {
        if (strcmp(argv[i], arg) == 0) {
            return(true);
        }
    }
    return(false);
}

bool checkIntOpt(int argc, const char** argv, const char* arg, int& argValue)
{
    for (int i = 1; i < argc - 1; i++) {
        if (strcmp(argv[i], arg) == 0) {
            if (argv[i+1][0] != '-') {
                argValue = (int) atof(argv[i+1]);
            }
            return(true);
        }
    }
    return(false);
}

// check the given parameters (argv) contain a specific unsigned integer option.
bool checkUnIntOpt(int argc, const char** argv, const char* arg, unsigned int& argValue)
{
    for (int i = 1; i < argc - 1; i++) {
        if (strcmp(argv[i], arg) == 0) {
            if (argv[i+1][0] != '-') {
                argValue = (unsigned int) atof(argv[i+1]);
            }
            return(true);
        }
    }
    return(false);
}

bool checkpCharOpt(int argc, const char** argv, const char* arg, char& argValue)
{
    for (int i = 1; i < argc - 1; i++) {
        if (strcmp(argv[i], arg) == 0) {
            int argLength = (int)strlen(argv[i+1]);
            if (argLength == 1) {
                argValue = argv[i+1][0];
                return(true);
            } else if (argLength == 3) {
                argValue = argv[i+1][1];
                return(true);
            } else {
                cout << "Unrecognizable delimiter " << argv[i+1] << "for read id." << endl;
                cout << "Space, tab and comma are the default delimiters." << endl;
                cout << "Put single quote around the delimiter." << endl;
            }
        }
    }
    return(false);
}

// check if the parameters (argv) contain a specific string option.
bool checkpStrOpt(int argc, const char** argv, const char* arg, string& argStr)
{
    for (int i = 1; i < argc - 1; i++) {
        if (strcmp(argv[i], arg) == 0) {
            if (argv[i+1][0] != '-') {
                argStr = string(argv[i+1]);
            }
            return(true);
        }
    }
    return(false);
}

// check if the parameters (argv) contain a specific string option.
bool checkpStrOpt(int argc, const char** argv, const char* arg, char* argStr)
{
    for (int i = 1; i < argc - 1; i++) {
        if (strcmp(argv[i], arg) == 0) {
            if (argv[i+1][0] != '-') {
                strcpy(argStr, argv[i+1]);
            }
            return(true);
        }
    }
    return(false);
}

void printWarning4FilteringNotSet(int ignoreDummyRLength, int ignoreRepeatReadLength, int readL)
{
    if (ignoreDummyRLength == 0 || ignoreDummyRLength == readL) {
        cout << "Info: opt --ignoreDummyR is not set."	<< endl;
        cout << "Low entroyp reads may significantly slowdown the running time." << endl;
    }
    if (ignoreRepeatReadLength == 0 || ignoreRepeatReadLength == readL) {
        cout << "Info: opt --ignoreRepeatR is not set."	<< endl;
        cout << "Reads with repetitive nt can't support splicing or deletion confidently." << endl;
    }
}

string getFullCommand(int argc, const char** argv)
{
    string fullCommand = string(argv[0]);
    for (int i = 1; i < argc; i++) {
        string tmpStr(argv[i]);
        fullCommand = fullCommand.append(" ").append(tmpStr);
    }
    return(fullCommand);
}

ParameterList getParameterList(int argc, const char** argv)
{
    ParameterList parameters;
    if (argc == 1) {
        printSynopsis();
    } else if (argc == 2) {
        printUsageInfo(argv[1]);
    } else {
        parameters.fullCommand = getFullCommand(argc, argv);
        CFlags f;
        myStrCpy(parameters.refFile, argv[1], FILENAME_MAX);
        f.checkpStrOpt(argc, argv, "--refFormat", parameters.refFormat);
        myStrCpy(parameters.readsFile, argv[2], FILENAME_MAX);
        f.checkpStrOpt(argc, argv, "--readFormat", parameters.readsFileFormat);
        if (argc > 3) {
            int DEFAULT_VAR_T = parameters.subDiffThreshold;
            parameters.subDiffThreshold = atoi(argv[3]);
            if (argv[3][0] != '0' && atoi(argv[3]) == 0) {
                parameters.subDiffThreshold = DEFAULT_VAR_T; // Arg not a number
            }
        }
        // The default is to output the best del alignments in term of number of mismatches.
        // The default will try to used the saved index table, without attempting to save table.
        parameters.bGetAllDelAlignments = f.checkArg(argc, argv, "-a");
        parameters.bUniqueMapOnly = f.checkArg(argc, argv, "-e");
        f.checkUnIntOpt(argc, argv, "-T", parameters.truncatedReadLength);
        f.checkIntOpt(argc, argv, "-v", parameters.subDiffThreshold);
        f.checkIntOpt(argc, argv, "-L", parameters.disUB);
        f.checkIntOpt(argc, argv, "-U", parameters.disLB);
        parameters.bMakeIndex = f.checkArg(argc, argv, "-m");
        parameters.bSaveIndex = f.checkArg(argc, argv, "-s");
        f.checkpStrOpt(argc, argv, "-s", parameters.indexFileN);
        parameters.bPrintUnMappedReads = f.checkArg(argc, argv,  "-u");

        f.checkpStrOpt(argc, argv, "-u", parameters.unmappedFileN);
        f.checkpStrOpt(argc, argv, "-o", parameters.outputFileN);
        f.checkUnIntOpt(argc, argv, "--anchorL", parameters.anchorLength);
        f.checkpStrOpt(argc, argv, "--seed", parameters.seedName);
        f.checkIntOpt(argc, argv, "--MEMES", parameters.MEMES);
        f.checkpStrOpt(argc, argv, "--outputFormat", parameters.outputFormat);
        parameters.bPrintSamHeader = !f.checkArg(argc, argv, "--noSamHeader");
        f.checkpStrOpt(argc, argv, "-d", parameters.outputDir);
        parameters.bFileterRepeatRead = f.checkArg(argc, argv, "--ignoreRepeatR");
        f.checkIntOpt(argc, argv, "--ignoreRepeatR", parameters.filteredRepeatBases);
        parameters.bFileterDummyRead = f.checkArg(argc, argv, "--ignoreDummyR");
        f.checkIntOpt(argc, argv, "--ignoreDummyR", parameters.filteredDummyBases);
        parameters.bPrintRef = f.checkArg(argc, argv, "--printRef");
        parameters.bCanoicalOnly = f.checkArg(argc, argv, "--canonicalJunc");
        // read filtering
        parameters.bDiscardReadWithN = !f.checkArg(argc, argv, "--includeReadsWN");
        // truncate the read ID
        f.checkpCharOpt(argc, argv, "--delimiter", parameters.readtag_delimiter);
        // for quality score (incomplete)
        parameters.bPrintAlignments = !f.checkArg(argc, argv, "--statsOnly");
        parameters.bIgnoreQS = f.checkArg(argc, argv, "--ignoreQS");
        // for storing the anchor head and tail ends
        parameters.bGetAllAlignments = !f.checkArg(argc, argv, "--bestAnchor");
        parameters.getOptsByCheckingExtName();
        ParameterList& P = parameters;
        printWarning4FilteringNotSet(P.filteredDummyBases, P.filteredRepeatBases, (int)P.readLength);
        parameters.bTest = f.checkArg(argc, argv, "--test");
        f.checkUnrecognizedFlags(argc, argv);
    }
    return(parameters);
}

bool withFastaExtFileName(const char* fileName)
{
    if (hasTheExtName(fileName, ".fasta") ||
            hasTheExtName(fileName, ".fna") ||
            hasTheExtName(fileName, ".mfa") ||
            hasTheExtName(fileName, ".fa")) {
        return (true);
    } else {
        return(false);
    }
}

bool withSupportExtFileName(const char* fileName)
{
    if (withFastaExtFileName(fileName) ||
            hasTheExtName(fileName, ".csfasta") ||
            hasTheExtName(fileName, ".csfa") ||
            hasTheExtName(fileName, ".fastqsanger") ||
            hasTheExtName(fileName, ".fastq") ||
            hasTheExtName(fileName, ".fq") ||
            hasTheExtName(fileName, ".csfastq") ||
            hasTheExtName(fileName, ".csfq")) {
        return (true);
    } else {
        return(false);
    }
}

/*
 * This function get the read set file names in a file list to vectors.
 * If reads are not paired, only readSetList1 will be filled.
 * If reads are paired, both readSetList1 and readSetList2 will be filled.
 */
bool getReadSetsFilenames(ParameterList &P, vector<string>& readSetList)
{
    if (fileExist(P.readsFile)) {
        if (hasTheExtName(P.readsFile, ".txt") || P.refFormat == "list") { // read files are in a list.
            LOG_INFO("Info %d: Reading the file as a read set list\n", FINE_LOG);
            char readSetFile[FILENAME_MAX];

            ifstream readsFileList(P.readsFile);
            while (GetNextFilenameFromListFile(readsFileList, readSetFile)) {
                readSetList.push_back(string(readSetFile));
            }
            readsFileList.close();
        } else if (withSupportExtFileName(P.readsFile) ||
                   withSupportExtFileName(P.readsFileFormat)) {
            readSetList.push_back(string(P.readsFile));
        } else {
            cout << " The reads file is not in a recognizable format (ext name).\n" << endl;
            return(false);
        }
    } else {
        if (atoi(P.readsFile) == 0 && !fileExist(P.readsFile)) {
            printf("Can't open reads file %s.", P.readsFile);
        }
        return(false);
    }
    return(true);
}

// return false if the ext name of readSet is not expected
bool checkFileListHasTheRightExt(vector<string>& readSetList)
{
    std::string extName;
    for ( vector<string>::iterator it = readSetList.begin();
            it != readSetList.end(); it++) {
        if ( it == readSetList.begin()) {
            extName = std::string(getExtName(it->c_str()));
        } else if ( *it == string("") ) {
            continue;
        } else {
            if (extName != std::string(getExtName(it->c_str()))) {
                cout << "Reads input file " << *it << " doesn't have the ext name " << extName << ".\n";
                return(false);
            }
        }
        if (!withSupportExtFileName(it->c_str())) {
            cout << "Reads input file " << *it << " has a unexpected ext name\n";
            return(false);
        }
    }
    return(true);
}

bool checkReadsSetNamesValidity(vector<string>& readSetsList)
{
    bool valid_flag = true;
    if (readSetsList.size() == 0) {
        cout << "There are no read sets to mapped " << endl;
        valid_flag = false;
    }
    return(valid_flag);
}


